﻿using FlyingCircusWebIS.Controllers.Utilidades;
using FlyingCircusWebIS.Models;
using FlyingCircusWebIS.ViewModels.AeroportoVM;
using System;
using System.Collections.Generic;
using System.Data.OleDb;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace FlyingCircusWebIS.Controllers
{
    public class AeroportoController : Controller
    {
        // Identificador das actions disponíveis no controller
        public const string INDEX_ACTION = "Index";
        public const string FORM_ACTION = "Form";
        public const string BUSCAR_ITENS_CIDADES_ACTION = "BuscarItensCidades";
        public const string DESATIVAR_ACTION = "Desativar";
        public const string ATIVAR_ACTION = "Ativar";


        public ActionResult Index()
        {
            AeroportoIndexVM vm = ConstruirIndexVM();
            return View(vm);
        }

        public ActionResult Form(int? id)
        {
            AeroportoFormVM vm;
            if (id.HasValue)
            {
                vm = ConstruirFormVMParaEdicao(id.Value);
                if (vm == null)
                    return new HttpNotFoundResult();
            } 
            else 
            {
                vm = ConstruirFormVMParaNovo();
            }
           
            return View(vm);
        }

        [HttpPost]
        public ActionResult Form(AeroportoFormVM vm)
        {
            Aeroporto registro = ConverterFormVM(vm);

            if (ModelState.IsValid)
            {
                if (vm.Edicao)
                    AtualizarRegistro(registro);
                else
                    InserirRegistro(registro);

                return RedirectToAction(INDEX_ACTION);
            }
            else
            {
                return View(vm);
            }

        }


        public JsonResult BuscarItensCidades(string uf)
        {
            var itens = ListarItensCidadesPorUF(uf);
            return Json(itens, JsonRequestBehavior.AllowGet);
        }


    
        public JsonResult Desativar(string id)
        {
            DesativarRegistroPorId(id);
            return Json(new JsonActionResultModel("Registro desativado com sucesso."));
        }

        

        public JsonResult Ativar(string id)
        {
            AtivarRegistroPorId(id);
            return Json(new JsonActionResultModel("Registro ativado com sucesso."));
        }

       

        // -----------------------------------------------------------------------------------------
        // Métodos auxiliares 
        // -----------------------------------------------------------------------------------------


        private AeroportoIndexVM ConstruirIndexVM()
        {
            List<AeroportoCidade> registros = ListarRegistrosAeroportoCidade();

            AeroportoIndexVM vm = new AeroportoIndexVM();
            vm.Registros = registros;
            vm.TotalRegistros = registros.Count;
            return vm;
        }


        private AeroportoFormVM ConstruirFormVMParaNovo()
        {
            AeroportoFormVM vm = new AeroportoFormVM();
            vm.Edicao = false;
            vm.ItensUF = ListarItensUF();
            vm.ItensCidades = ListarItensCidadesParaNovo();
            
            return vm;
        }



   
        private AeroportoFormVM ConstruirFormVMParaEdicao(int id)
        {
            Aeroporto registro = BuscarRegistroPorId(id);
            if (registro != null)
            {
                int idCidade = registro.IdCidade;
                string UF = BuscarUFCidadePorId(idCidade);

                AeroportoFormVM vm = ConverterFormVM(registro);
                vm.UF = UF;
                vm.ItensUF = ListarItensUF();
                vm.ItensCidades = ListarItensCidadesPorUF(UF);
                vm.Edicao = true;
                return vm;
            }

            return null;
        }


        private AeroportoFormVM ConverterFormVM(Aeroporto registro)
        {
            AeroportoFormVM vm = new AeroportoFormVM();
            vm.IdAeroporto = registro.IdAeroporto;
            vm.NomeAeroporto = registro.NomeAeroporto;
            vm.Latitude = registro.Latitude.ToString();
            vm.Longitude = registro.Longitude.ToString();
            vm.IdCidade = registro.IdCidade;
            vm.FlagAtivo = registro.FlagAtivo.Equals("S");

            return vm;
        }



        private Aeroporto ConverterFormVM(AeroportoFormVM vm)
        {
            Aeroporto registro = new Aeroporto();
            registro.IdAeroporto = vm.IdAeroporto;
            registro.NomeAeroporto = vm.NomeAeroporto;
            registro.Latitude = Double.Parse(vm.Latitude, System.Globalization.CultureInfo.InvariantCulture);
            registro.Longitude = Double.Parse(vm.Longitude, System.Globalization.CultureInfo.InvariantCulture);
            registro.IdCidade = vm.IdCidade;
            registro.FlagAtivo = (vm.FlagAtivo ? "S" : "N");
            
            return registro;
        }



        // TODO: Este método deveria estar aqui? Duplicação de código com as regras de Cidade.
        // Desenvolvimento em camadas seria a solução? :)
        private List<SelectListItem> ListarItensCidadesPorUF(string UF)
        {
            List<Cidade> cidades = ListarRegistrosCidadesAtivasPorUF(UF);
            List<SelectListItem> itens = ConverterRegistrosCidadesParaItens(cidades);
            return itens;
        }

        // TODO: Este método deveria estar aqui? Duplicação de código com as regras de Cidade.
        // Desenvolvimento em camadas seria a solução? :)
        private List<SelectListItem> ListarItensCidadesParaNovo()
        {
            List<SelectListItem> itens = new List<SelectListItem>();
            itens.Add(new SelectListItem() { Text = "<Nenhum>", Value = "" });
            return itens;
        }



        // TODO: Este método deveria estar aqui? Duplicação de código com as regras de Cidade.
        // Desenvolvimento em camadas seria a solução? :)
        private List<SelectListItem> ConverterRegistrosCidadesParaItens(List<Cidade> cidades)
        {
            List<SelectListItem> itens = new List<SelectListItem>();
            itens.Add(new SelectListItem { Text = "<Nenhum>", Value = "" });
            foreach (var cidade in cidades)
            {
                itens.Add(new SelectListItem() { Text = cidade.NomeCidade, Value = cidade.IdCidade.ToString() });
            }
            return itens;
        }




        // TODO: Este método deveria estar aqui? Duplicação de código com as regras de Cidade.
        // Desenvolvimento em camadas seria a solução? :)
        private List<SelectListItem> ListarItensUF()
        {
            List<SelectListItem> itens = new List<SelectListItem>();
            itens.Add(new SelectListItem { Text = "<Nenhum>", Value = "" });
            itens.Add(new SelectListItem { Text = "Acre", Value = "AC" });
            itens.Add(new SelectListItem { Text = "Alagoas", Value = "AL" });
            itens.Add(new SelectListItem { Text = "Amapá", Value = "AP" });
            itens.Add(new SelectListItem { Text = "Amazonas", Value = "AM" });
            itens.Add(new SelectListItem { Text = "Bahia", Value = "BA" });
            itens.Add(new SelectListItem { Text = "Ceará", Value = "CE" });
            itens.Add(new SelectListItem { Text = "Distrito Federal", Value = "DF" });
            itens.Add(new SelectListItem { Text = "Espírito Santo", Value = "ES" });
            itens.Add(new SelectListItem { Text = "Goiás", Value = "GO" });
            itens.Add(new SelectListItem { Text = "Maranhão", Value = "MA" });
            itens.Add(new SelectListItem { Text = "Mato Grosso", Value = "MT" });
            itens.Add(new SelectListItem { Text = "Mato Grosso do Sul", Value = "MS" });
            itens.Add(new SelectListItem { Text = "Minas Gerais", Value = "MG" });
            itens.Add(new SelectListItem { Text = "Pará", Value = "PA" });
            itens.Add(new SelectListItem { Text = "Paraíba", Value = "PB" });
            itens.Add(new SelectListItem { Text = "Paraná", Value = "PR" });
            itens.Add(new SelectListItem { Text = "Pernambuco", Value = "PE" });
            itens.Add(new SelectListItem { Text = "Piauí", Value = "PI" });
            itens.Add(new SelectListItem { Text = "Rio de Janeiro", Value = "RJ" });
            itens.Add(new SelectListItem { Text = "Rio Grande do Norte", Value = "RN" });
            itens.Add(new SelectListItem { Text = "Rio Grande do Sul", Value = "RS" });
            itens.Add(new SelectListItem { Text = "Rondônia", Value = "RO" });
            itens.Add(new SelectListItem { Text = "Roraima", Value = "RR" });
            itens.Add(new SelectListItem { Text = "Santa Catarina", Value = "SC" });
            itens.Add(new SelectListItem { Text = "São Paulo", Value = "SP" });
            itens.Add(new SelectListItem { Text = "Sergipe", Value = "SE" });
            itens.Add(new SelectListItem { Text = "Tocantins", Value = "TO" });

            return itens;
        }

  




        // ----------------------------------------------------------------------------------
        // Métodos auxiliares de acesso ao banco de dados.
        //
        // Os métodos abaixo se comunicam diretamente com o banco de dados.
        // ----------------------------------------------------------------------------------

        private void InserirRegistro(Aeroporto registro)
        {
            string sqlAtualizar = "insert into AEROPORTO (IdAeroporto, NomeAeroporto, Latitude, Longitude, IdCidade, FlagAtivo) values (seqAeroporto.nextVal, ?, ?, ?, ?, ?)";
            GerenciadorConexao gerenciadorConexao = new GerenciadorConexao();

            // Abre a conexão
            gerenciadorConexao.Abrir();

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = gerenciadorConexao.Conexao;
            comando.CommandText = sqlAtualizar;

            OleDbParameter pNome = new OleDbParameter("NomeAeroporto", OleDbType.VarChar);
            pNome.Value = registro.NomeAeroporto;
            comando.Parameters.Add(pNome);

            OleDbParameter pLatitude = new OleDbParameter("Latitude", OleDbType.Numeric);
            pLatitude.Value = registro.Latitude;
            comando.Parameters.Add(pLatitude);

            OleDbParameter pLongitude = new OleDbParameter("Longitude", OleDbType.Numeric);
            pLongitude.Value = registro.Longitude;
            comando.Parameters.Add(pLongitude);

            OleDbParameter pIdCidade = new OleDbParameter("IdCidade", OleDbType.Integer);
            pIdCidade.Value = registro.IdCidade;
            comando.Parameters.Add(pIdCidade);

            OleDbParameter pAtivo = new OleDbParameter("FlagAtivo", OleDbType.VarChar);
            pAtivo.Value = registro.FlagAtivo;
            comando.Parameters.Add(pAtivo);

            // Insert
            comando.ExecuteNonQuery();

            // Fecha a conexão
            gerenciadorConexao.Fechar();
        }

        private void AtualizarRegistro(Aeroporto registro)
        {
            string sqlAtualizar = "update AEROPORTO set NomeAeroporto = ?, Latitude = ?, Longitude = ?, IdCidade = ?, FlagAtivo = ? where IdAeroporto = ?";
            GerenciadorConexao gerenciadorConexao = new GerenciadorConexao();

            // Abre a conexão
            gerenciadorConexao.Abrir();

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = gerenciadorConexao.Conexao;
            comando.CommandText = sqlAtualizar;

            OleDbParameter pNome = new OleDbParameter("NomeAeroporto", OleDbType.VarChar);
            pNome.Value = registro.NomeAeroporto;
            comando.Parameters.Add(pNome);

            OleDbParameter pLatitude = new OleDbParameter("Latitude", OleDbType.Numeric);
            pLatitude.Value = registro.Latitude;
            comando.Parameters.Add(pLatitude);

            OleDbParameter pLongitude = new OleDbParameter("Longitude", OleDbType.Numeric);
            pLongitude.Value = registro.Longitude;
            comando.Parameters.Add(pLongitude);

            OleDbParameter pIdCidade = new OleDbParameter("IdCidade", OleDbType.Integer);
            pIdCidade.Value = registro.IdCidade;
            comando.Parameters.Add(pIdCidade);

            OleDbParameter pAtivo = new OleDbParameter("FlagAtivo", OleDbType.VarChar);
            pAtivo.Value = registro.FlagAtivo;
            comando.Parameters.Add(pAtivo);

            OleDbParameter pIdAeroporto = new OleDbParameter("IdAeroporto", OleDbType.Integer);
            pIdAeroporto.Value = registro.IdAeroporto;
            comando.Parameters.Add(pIdAeroporto);


            // Update
            comando.ExecuteNonQuery();

            // Fecha a conexão
            gerenciadorConexao.Fechar();
        }



        private void AtivarRegistroPorId(string id)
        {
            string sqlAtualizar = "update AEROPORTO set flagAtivo = 'S' where IdAeroporto = ?";
            GerenciadorConexao gerenciadorConexao = new GerenciadorConexao();

            // Abre a conexão
            gerenciadorConexao.Abrir();

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = gerenciadorConexao.Conexao;
            comando.CommandText = sqlAtualizar;

            OleDbParameter pId = new OleDbParameter("IdAeroporto", OleDbType.VarChar);
            pId.Value = id;
            comando.Parameters.Add(pId);

            // Update
            comando.ExecuteNonQuery();

            // Fecha a conexão
            gerenciadorConexao.Fechar();
        }


        private void DesativarRegistroPorId(string id)
        {
            string sqlAtualizar = "update AEROPORTO set flagAtivo = 'N' where IdAeroporto = ?";
            GerenciadorConexao gerenciadorConexao = new GerenciadorConexao();

            // Abre a conexão
            gerenciadorConexao.Abrir();

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = gerenciadorConexao.Conexao;
            comando.CommandText = sqlAtualizar;

            OleDbParameter pId = new OleDbParameter("IdAeroporto", OleDbType.VarChar);
            pId.Value = id;
            comando.Parameters.Add(pId);


            // Update
            comando.ExecuteNonQuery();

            // Fecha a conexão
            gerenciadorConexao.Fechar();
        }

        private Aeroporto BuscarRegistroPorId(int id)
        {
            Aeroporto registro = null;
            string sqlBuscar = "select * from AEROPORTO where IdAeroporto = ?";
            GerenciadorConexao gerenciadorConexao = new GerenciadorConexao();
            
            // Abre a conexão
            gerenciadorConexao.Abrir();
            
            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = gerenciadorConexao.Conexao;
            comando.CommandText = sqlBuscar;

            OleDbParameter pId = new OleDbParameter("IdAeroporto", OleDbType.Integer);
            pId.Value = id;
            comando.Parameters.Add(pId);

            // Select
            OleDbDataReader dr = comando.ExecuteReader();
            if (dr.Read())
            {
                registro = ConverterDataReaderParaObj(dr);
            }

            // Fecha a conexão
            gerenciadorConexao.Fechar();
            
            return registro;
        }


        private List<Aeroporto> ListarRegistros()
        {
            GerenciadorConexao gerenciadorConexao = new GerenciadorConexao();
            String sqlConsulta = "select * from AEROPORTO";
            
            // Abre a conexão 
            gerenciadorConexao.Abrir();

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = gerenciadorConexao.Conexao;
            comando.CommandText = sqlConsulta;

            // Select
            OleDbDataReader dr = comando.ExecuteReader();

            List<Aeroporto> registros = new List<Aeroporto>();
            while (dr.Read())
            {
                Aeroporto registro = ConverterDataReaderParaObj(dr);
                registros.Add(registro);
            }

            // Fecha a conexão
            gerenciadorConexao.Fechar();

            return registros;
        }



        private Aeroporto ConverterDataReaderParaObj(OleDbDataReader dr)
        {
            Aeroporto registro = new Aeroporto();
            registro.IdAeroporto = Int32.Parse(dr["IdAeroporto"].ToString());
            registro.NomeAeroporto = dr["NomeAeroporto"].ToString();
            registro.Latitude = Double.Parse(dr["Latitude"].ToString());
            registro.Longitude = Double.Parse(dr["Longitude"].ToString());
            registro.IdCidade = Int32.Parse(dr["IdCidade"].ToString());
            registro.FlagAtivo = dr["FlagAtivo"].ToString();

            return registro;
        }


        private List<AeroportoCidade> ListarRegistrosAeroportoCidade()
        {
            GerenciadorConexao gerenciadorConexao = new GerenciadorConexao();
            String sqlConsulta = "select * from AeroportoCidadeView";

            // Abre a conexão 
            gerenciadorConexao.Abrir();

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = gerenciadorConexao.Conexao;
            comando.CommandText = sqlConsulta;

            // Select
            OleDbDataReader dr = comando.ExecuteReader();

            List<AeroportoCidade> registros = new List<AeroportoCidade>();
            while (dr.Read())
            {
                AeroportoCidade registro = new AeroportoCidade();
                registro.IdAeroporto = Int32.Parse(dr["IdAeroporto"].ToString());
                registro.NomeAeroporto = dr["NomeAeroporto"].ToString();
                registro.FlagAtivo = dr["FlagAtivo"].ToString();
                registro.IdCidade = Int32.Parse(dr["IdCidade"].ToString());
                registro.NomeCidade = dr["NomeCidade"].ToString();
                registro.UF = dr["UF"].ToString();
                registro.Pais = dr["Pais"].ToString();

                registros.Add(registro);
            }

            // Fecha a conexão
            gerenciadorConexao.Fechar();

            return registros;
        }




        // TODO: Este método deveria estar aqui? Duplicação de código com as regras de Cidade.
        // Desenvolvimento em camadas seria a solução? :)
        private string BuscarUFCidadePorId(int idCidade)
        {
            GerenciadorConexao gerenciadorConexao = new GerenciadorConexao();
            String sqlConsulta = "select UF from CIDADE where IdCidade = ?";
            
            // Abre a conexão
            gerenciadorConexao.Abrir();

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = gerenciadorConexao.Conexao;
            comando.CommandText = sqlConsulta;

            OleDbParameter pId = new OleDbParameter("IdCidade", OleDbType.VarChar);
            pId.Value = idCidade;
            comando.Parameters.Add(pId);

            // Select
            OleDbDataReader dr = comando.ExecuteReader();

            string UF = null;
            if (dr.Read())
            {
                UF = dr["UF"].ToString();
            }

            // Fecha a conexão
            gerenciadorConexao.Fechar();

            return UF;
        }



        // TODO: Este método deveria estar aqui? Duplicação de código com as regras de Cidade.
        // Desenvolvimento em camadas seria a solução? :)
        private List<Cidade> ListarRegistrosCidadesAtivasPorUF(string UF)
        {
            GerenciadorConexao gerenciadorConexao = new GerenciadorConexao();
            String sqlConsulta = "select * from CIDADE where UF = ? and FlagAtivo = 'S'";

            // Abre a conexão
            gerenciadorConexao.Abrir();

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = gerenciadorConexao.Conexao;
            comando.CommandText = sqlConsulta;

            OleDbParameter pUF = new OleDbParameter("UF", OleDbType.VarChar);
            pUF.Value = UF;
            comando.Parameters.Add(pUF);


            // Select
            OleDbDataReader dr = comando.ExecuteReader();

            List<Cidade> cidades = new List<Cidade>();
            while (dr.Read())
            {
                Cidade registro = new Cidade();
                registro.IdCidade = Int32.Parse(dr["IdCidade"].ToString());
                registro.NomeCidade = dr["NomeCidade"].ToString();
                registro.Pais = dr["Pais"].ToString();
                registro.UF = dr["UF"].ToString();
                registro.FlagAtivo = dr["FlagAtivo"].ToString();

                cidades.Add(registro);
            }

            // Fecha a conexão
            gerenciadorConexao.Fechar();


            return cidades;
        }

    }
}
